#include "Graph.h"

EDGE::EDGE(string source1="", string dest1="", string weight1="",string Fake1="", string Fake2=""){
	source=source1;
	dest=dest1;
	weight=weight1;
	Fakesource=Fake1;
	FakeDest=Fake2;
}

 
NODE::NODE(string data1="", string type1="",string Fake1=""){
	data=data1;
	type=type1;
	Fake=Fake1;
}

void NODE::print(){cout<<"node "<<data<<": "<<endl;for (int i=0;i<adjEdges.size();i++)cout<<adjEdges[i].source<<" to "<<adjEdges[i].dest<<" with "<<adjEdges[i].weight<<endl;}

string __NOT::getType(int i){
	string s="operator";
	if (i==0)
		s="variable";
	else if (i==1)
		s="constant";
	return s;
}
__NOT::__NOT (){
	numbOfNodes=0;
	isNot=0;
	MAXnumb=pow(10.0,8);
	Type[0]="INT";
	Type[1]="REAL";
	Type[2]="SET";
	Type[3]="MAP";
	Type[4]="TUPLE";
}
void __NOT::print(){
	for (int i=0;i<adjlistout.size();i++){
		cout<<adjplacee[i]<<" :   ";
		for (int j=0;j<adjlistout[i].size();j++)
			cout<<adjlistout[i][j]<<"    ";
		cout<<endl;
	}
}
int __NOT::getNumber(string s){
	if (s=="INT")
		return 3;
	else if (s=="REAL")
		return 4;
	else if (s=="SET")
		return 5;
	else if (s=="MAP")
		return 6;
	else if (s=="TUPLE")
		return 7;
	return 0;
}
string __NOT::headName(int i){
	ostringstream temp;
               temp<<i;
               string m="head"+temp.str();
	return m;
}

string __NOT::FillI(int i){
	string type;
	if (nodeType[adjplacee[i]].first==0)
		type=VartoType[nodeType[adjplacee[i]].second];
	else if (adjplacee[i]==":=")
		type="Statement";
	else
		type="Expression";				
	NODE Anode(nodeType[adjplacee[i]].second,type,adjplacee[i]);
	Nodes.push_back(Anode);
	NodeToIndex[adjplacee[i]]=numbOfNodes;
	numbOfNodes++;
	AlreadyCreated[nodeType[adjplacee[i]].second]=1;
	return type;
}
string __NOT::FillIJ(int i, int j){
	string realName;
	if (nodeType[adjlistout[i][j]].first==0){
		realName=nodeType[adjlistout[i][j]].second;
	}
	else
		realName=adjlistout[i][j];
	if (nodeType[realName].first!=2){
		string type;	
		if (nodeType[realName].first==0)
			type=VartoType[nodeType[adjlistout[i][j]].second];
		else
			type="Literal";
		string xyz=getTempname(adjlistout[i][j]);
		FakeOf[adjlistout[i][j]]=xyz;
		NODE Anode(nodeType[adjlistout[i][j]].second,type,xyz);
		Nodes.push_back(Anode);
		NodeToIndex[xyz]=numbOfNodes;
		numbOfNodes++;
	}
return realName;
}

void __NOT::Construct(){
	int k;		
	for (int i=0;i<adjlistout.size();i++){
		string lhead = headName(i);
		string type=FillI(i);
	}
	bool *A=new bool [adjlistout.size()];
	for(int i=0;i<adjlistout.size();i++)
		A[i]=true;
	k=adjlistout.size();
	for (int i=0;i<adjlistout.size();i++){
		string source = headName(i);
		for (int j=0;j<adjlistout[i].size();j++){
			string dest;
			if(nodeType[adjlistout[i][j]].first!=2){
				dest=headName(k);	
				k++;				
				string realName=FillIJ(i,j);
			}
			else {
				A[adjplace[adjlistout[i][j]]]=false;
				dest=headName(adjplace[adjlistout[i][j]]);					
			}
			if (nodeType[adjlistout[i][j]].second==":=") {
				int ind1, ind2;
				EDGE Eedge(nodeType[adjplacee[i]].second,":=","definition",adjplacee[i],adjlistout[i][j]);
				ind1=NodeToIndex[adjplacee[i]];
				Nodes[ind1].adjEdges.push_back(Eedge);
				Edges.push_back(Eedge);
				EDGE Eedge2(":=",nodeType[adjplacee[i]].second,"right",adjlistout[i][j],adjplacee[i]);
				ind2=NodeToIndex[adjlistout[i][j]];
				Edges.push_back(Eedge2);
				Nodes[ind2].adjEdges.push_back(Eedge2);	
			}
			else{
				int ind=NodeToIndex[adjplacee[i]];
				if(nodeType[adjlistout[i][j]].first!=2){
					if(j==0){
						EDGE Eedge(nodeType[adjplacee[i]].second,nodeType[adjlistout[i][j]].second,"left",adjplacee[i],FakeOf[adjlistout[i][j]]);						
						Nodes[ind].adjEdges.push_back(Eedge);
						Edges.push_back(Eedge);
					}
					else{
						EDGE Eedge(nodeType[adjplacee[i]].second,nodeType[adjlistout[i][j]].second,"right",adjplacee[i],FakeOf[adjlistout[i][j]]);
						Nodes[ind].adjEdges.push_back(Eedge);
					Edges.push_back(Eedge);
					}
				}
				else{
					if(j==0){
						EDGE Eedge(nodeType[adjplacee[i]].second,nodeType[adjlistout[i][j]].second,"left",adjplacee[i],adjlistout[i][j]);
						Nodes[ind].adjEdges.push_back(Eedge);
						Edges.push_back(Eedge);						
						}
					else {
						EDGE Eedge(nodeType[adjplacee[i]].second,nodeType[adjlistout[i][j]].second,"right",adjplacee[i],adjlistout[i][j]);
						Nodes[ind].adjEdges.push_back(Eedge);
						Edges.push_back(Eedge);
					}
				}					
			}	
		}
	}
}
void __NOT::checkandadd(string a){
	int bindex;
	if (countt[a]==0){
		vector<string> temp;
		adjlistout.push_back(temp);
		countt[a]++;
		bindex=adjlistout.size()-1;
		adjplace[a]=bindex;
		adjplacee[bindex]=a;
	}
}

string __NOT::getname(string m){
	countt[m]++;
	string l = m;
	ostringstream temp;
	temp<<countt[m];
	m+=temp.str();
	nodeType[m]=make_pair(2,l);
	return m;
}
	
string __NOT::getTempname(string m){
	countt[m]++;
	string l = m;
	ostringstream temp;
	temp<<countt[m];
	m+=temp.str();
	return m;
}
 string __NOT::getnameVar(string m){
	if (VartoType[m]=="LIT"){
		countt[m]++;
	        string l = m;
                ostringstream temp;
                temp<<countt[m];
                m+=temp.str();
                nodeType[m]=make_pair(1,l);
		}
	else{
                countt[m]++;
	        string l = m;
                ostringstream temp;
                temp<<countt[m];
                m+=temp.str();
                nodeType[m]=make_pair(0,l);
	}
        return m;
}
void __NOT::setType(string m, int i){
	if (i>2){
		nodeType[m]=make_pair(0,m);
		if (countt[m]==0){
			VartoType[m]=Type[i-3];
		}
	}
	else if (i==1){
		nodeType[m]=make_pair(i,m);
		VartoType[m]="LIT";
	}
	else	
		nodeType[m]=make_pair(i,m);
	
}
char* __NOT::RootReturn(string oper, string opera1, string opera2){
	string opernew = getname(oper);
	checkandadd(opernew);
	if (countt[opera1]==0 || nodeType[opera1].first==2)
		adjlistout[adjplace[opernew]].push_back(opera1);
	else
		adjlistout[adjplace[opernew]].push_back(dependencies[opera1]);
	if (countt[opera2]==0 || nodeType[opera2].first==2)
		adjlistout[adjplace[opernew]].push_back(opera2);
	else
		adjlistout[adjplace[opernew]].push_back(dependencies[opera2]);
	char * l = (char *)opernew.c_str();
	return l;
}

char * __NOT:: CreateAssignment(string oper1, string assig, string oper2){
	if (assig=="PROJ")
		cout<<oper1<<endl;
	string operand = getnameVar(oper1);
	dependencies[oper1]=operand;
	checkandadd(operand);
	string opernew = getname(assig);
	checkandadd(opernew);
	adjlistout[adjplace[operand]].push_back(opernew);
	if (nodeType[oper2].first==1){
		string operr2=getnameVar(oper2);
		adjlistout[adjplace[opernew]].push_back(operr2);
	}
	else if ((countt[oper2]==0 || nodeType[oper2].first==2))
		adjlistout[adjplace[opernew]].push_back(oper2);
	else
		adjlistout[adjplace[opernew]].push_back(dependencies[oper2]);
	char *l = (char *)opernew.c_str();
	return l;
}

char * __NOT::CardinAssig (string oper, string opera){
	string opernew = getname(oper);
	checkandadd(opernew);
	if(nodeType[opera].first==1){
		string operr2=getnameVar(opera);
		adjlistout[adjplace[opernew]].push_back(operr2);			
	}
	else if (countt[opera]==0)
		adjlistout[adjplace[opernew]].push_back(opera);
	else
		adjlistout[adjplace[opernew]].push_back(dependencies[opera]);
	char *l = (char *)opernew.c_str();
	return l;
}
